﻿//-----------------------------------------------------------------------
// <copyright file="BaseRepository.cs" company="SLWY Enterprises">
// * Copyright (C) 2017 四川商旅无忧科技有限公司 版权所有。
// * version : 1.0
// * author  : qinchaoyue
// * FileName: BaseRepository.cs
// * history : created by qinchaoyue 2018-01-10 04:45:13
// </copyright>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using Slwy.Data.Entity.Attributes;
using Slwy.Data.Entity.Helper;
using Slwy.Data.Entity.Interfaces;
using Slwy.Data.Entity.Models;
using Slwy.Logger.Contracts;
using Slwy.Utility.Extensions;
using SqlSugar;

namespace Slwy.Data.Entity
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity>
        where TEntity : class, new()
    {
        private readonly ILogger _logger;

        private string ReadDbName = "ConnectionRead";
        private string WriteDbName = "ConnectionWrite";

        public static Dictionary<string, Stack<MTablePart>> _tableParts = new Dictionary<string, Stack<MTablePart>>();

        private IUnitOfWork _unitOfWork;

        public Func<SqlSugarClient, string, bool> OnSaveChanged
        {
            get => _unitOfWork.OnSaveChanged;
            set => _unitOfWork.OnSaveChanged += value;
        }

        public SqlSugarClient Client { get; set; }

        public BaseRepository(ILogger logger, IUnitOfWork unitOfWork)
        {
            this._logger = logger;
            this._unitOfWork = unitOfWork;
            this.Init();
        }

        /// <summary>
        /// 初始化
        /// 修改类和表的映射关系
        /// </summary>
        private void Init()
        {
            if (typeof(TEntity).HasAttribute<DbConnectionNameAttribute>(true))
            {
                WriteDbName = typeof(TEntity).GetDbConnectionName();
                if (WriteDbName.IndexOf("Write", StringComparison.Ordinal) == -1)
                {
                    WriteDbName += "Write";
                }
            }

            if (!this._unitOfWork.DbSet.TryGetValue(WriteDbName, out var v))
            {
                throw new ArgumentNullException($"数据库链接 {WriteDbName} 不存在.请检查配置文件.");
            }
            this.Client = v;
            var typeName = typeof(TEntity).Name;
            var tableName = typeName.Replace("Entity", string.Empty);
            this.Client?.MappingTables.Add(typeName, tableName);
        }

        [Obsolete("请使用属性方式切换数据库连接")]
        public void SetConnection(string connectWriteName, string connectReadName, string suffix = "")
        {
            ReadDbName = connectReadName;
            WriteDbName = connectWriteName;
            Init();
            // base.SetConnection(connectWriteName, connectReadName, suffix);
        }

        [Obsolete("请使用属性方式切换数据库连接")]
        public void SetConnection(string suffix)
        {
            // base.SetConnection(suffix);
        }

        /// <summary>
        /// 执行sql语句
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="sql">sql 语句</param>
        /// <param name="parameters">变量 </param>
        /// <returns>结果集合</returns>
        public List<T> SqlQuery<T>(string sql, object parameters = null)
        {
            return this.Client.Ado.SqlQuery<T>(sql, parameters);
        }

        /// <summary>
        /// 执行sql语句
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public int ExecuteCommand(string sql, object parameters = null)
        {
            return this.Client.Ado.ExecuteCommand(sql, parameters);
        }

        public ISugarQueryable<TEntity> Entities => this.Client.Queryable<TEntity>().AS(TableHelper.GetTableName<TEntity>());

        public bool TransactionEnabled
        {
            get => this._unitOfWork.GetTransactionEnabled(WriteDbName);
            set
            {
                if (value)
                {
                    _unitOfWork.SetTransactionEnabled(true, WriteDbName);
                }
            }
        }


        public IUpdateable<TEntity> Updateable(TEntity entity)
        {
            return this.Client.Updateable<TEntity>(entity);
        }

        public IUpdateable<TEntity> Updateable()
        {
            return this.Client.Updateable<TEntity>();
        }

        public IUpdateable<TEntity> Updateable(IList<TEntity> entities)
        {
            return this.Client.Updateable<TEntity>(entities);
        }

        public IUpdateable<TEntity> Updateable(TEntity[] entities)
        {
            return this.Client.Updateable(entities);
        }

        public IInsertable<TEntity> Insert(TEntity entity)
        {
            return this.Client.Insertable(entity);
        }

        public IInsertable<TEntity> Insert(List<TEntity> entity)
        {
            return this.Client.Insertable(entity);
        }

        public IInsertable<TEntity> Insert(TEntity[] entity)
        {
            return this.Client.Insertable(entity);
        }

        public bool SaveChanges()
        {
            return this._unitOfWork.SaveChanges(WriteDbName);
        }
    }
}
